package edu.northwestern.cbits.purple_robot_manager.probes.builtin; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import edu.northwestern.cbits.purple_robot_manager.R; import edu.northwestern.cbits.purple_robot_manager.activities.WebkitActivity; import edu.northwestern.cbits.purple_robot_manager.activities.WebkitLandscapeActivity; import edu.northwestern.cbits.purple_robot_manager.charts.SplineChart; import edu.northwestern.cbits.purple_robot_manager.db.ProbeValuesProvider; import edu.northwestern.cbits.purple_robot_manager.logging.LogManager; import edu.northwestern.cbits.purple_robot_manager.probes.Probe; public class StepCounterProbe extends Probe implements SensorEventListener { private static final String DB_TABLE = "step_counter_probe"; private static final String STEPS_KEY = "STEPS"; private static final boolean DEFAULT_ENABLED = false; private static final String STEP_COUNT = "STEP_COUNT"; private static final String ENABLED = "config_probe_step_counter_enabled"; private float _steps = 0; private Context _context; @Override public String getPreferenceKey() { return "built_in_step_counter"; } @Override public Intent viewIntent(Context context) { Intent i = new Intent(context, WebkitLandscapeActivity.class); return i; } @Override public String probeCategory(Context context) { return context.getResources().getString(R.string.probe_sensor_category); } @Override public String contentSubtitle(Context context) { Cursor c = ProbeValuesProvider.getProvider(context).retrieveValues(context, StepCounterProbe.DB_TABLE, this.databaseSchema()); int count = -1; if (c != null) { count = c.getCount(); c.close(); } return String.format(context.getString(R.string.display_item_count), count); } public Map<String, String> databaseSchema() { HashMap<String, String> schema = new HashMap<>(); schema.put(StepCounterProbe.STEPS_KEY, ProbeValuesProvider.REAL_TYPE); return schema; } @Override public String getDisplayContent(Activity activity) { try { String template = WebkitActivity.stringForAsset(activity, "webkit/chart_spline_full.html"); SplineChart c = new SplineChart(); ArrayList<Double> battery = new ArrayList<>(); ArrayList<Double> time = new ArrayList<>(); Cursor cursor = ProbeValuesProvider.getProvider(activity).retrieveValues(activity, StepCounterProbe.DB_TABLE, this.databaseSchema()); int count = -1; if (cursor != null) { count = cursor.getCount(); while (cursor.moveToNext()) { double d = cursor.getDouble(cursor.getColumnIndex(StepCounterProbe.STEPS_KEY)); double t = cursor.getDouble(cursor.getColumnIndex(ProbeValuesProvider.TIMESTAMP)); battery.add(d); time.add(t); } cursor.close(); } c.addSeries(activity.getString(R.string.step_count_label), battery); c.addTime(activity.getString(R.string.step_count_time_label), time); JSONObject json = c.dataJson(activity); template = template.replace("{{{ highchart_json }}}", json.toString()); template = template.replace("{{{ highchart_count }}}", "" + count); return template; } catch (IOException | JSONException e) { LogManager.getInstance(activity).logException(e); } return null; } @Override public String name(Context context) { return "edu.northwestern.cbits.purple_robot_manager.probes.builtin.StepCounterProbe"; } @Override public String title(Context context) { return context.getString(R.string.title_step_counter_probe); } @Override @SuppressLint("InlinedApi") public boolean isEnabled(Context context) { if (Build.VERSION.SDK_INT < 19) return false; this._context = context.getApplicationContext(); SharedPreferences prefs = ContinuousProbe.getPreferences(context); SensorManager sensors = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); Sensor sensor = sensors.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); sensors.unregisterListener(this, sensor); if (super.isEnabled(context)) { if (prefs.getBoolean(StepCounterProbe.ENABLED, ContinuousProbe.DEFAULT_ENABLED)) { sensors.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, null); return true; } } return false; } @Override public void enable(Context context) { SharedPreferences prefs = Probe.getPreferences(context); Editor e = prefs.edit(); e.putBoolean(StepCounterProbe.ENABLED, true); e.commit(); } @Override public void disable(Context context) { SharedPreferences prefs = Probe.getPreferences(context); Editor e = prefs.edit(); e.putBoolean(StepCounterProbe.ENABLED, false); e.commit(); } @Override public String summarizeValue(Context context, Bundle bundle) { double steps = bundle.getDouble(StepCounterProbe.STEP_COUNT); return String.format(context.getResources().getString(R.string.summary_step_counter_probe), (int) steps); } @Override public String summary(Context context) { return context.getString(R.string.summary_step_counter_probe_desc); } @Override @SuppressWarnings("deprecation") public PreferenceScreen preferenceScreen(Context context, PreferenceManager manager) { PreferenceScreen screen = super.preferenceScreen(context, manager); screen.setTitle(this.title(context)); screen.setSummary(R.string.summary_step_counter_probe_desc); CheckBoxPreference enabled = new CheckBoxPreference(context); enabled.setTitle(R.string.title_enable_probe); enabled.setKey(StepCounterProbe.ENABLED); enabled.setDefaultValue(StepCounterProbe.DEFAULT_ENABLED); screen.addPreference(enabled); return screen; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { float steps = event.values[0]; if (this._steps < steps) { Bundle bundle = new Bundle(); bundle.putString("PROBE", this.name(this._context)); bundle.putLong("TIMESTAMP", event.timestamp / 1000000000); bundle.putFloat(StepCounterProbe.STEP_COUNT, steps); this.transmitData(this._context, bundle); Map<String, Object> values = new HashMap<>(); values.put(StepCounterProbe.STEPS_KEY, bundle.getFloat("STEPS")); values.put(ProbeValuesProvider.TIMESTAMP, (double) bundle.getLong("TIMESTAMP")); ProbeValuesProvider.getProvider(this._context).insertValue(this._context, StepCounterProbe.DB_TABLE, this.databaseSchema(), values); this._steps = steps; } } @Override public JSONObject fetchSettings(Context context) { JSONObject settings = super.fetchSettings(context); if (Build.VERSION.SDK_INT < 19) return new JSONObject(); return settings; } }